package com.bflow.impl;

import com.bflow.api.*;
import com.bflow.api.bo.*;
import com.bflow.api.constant.BflowConstant.*;
import com.bflow.commons.consts.CommConst;
import com.bflow.commons.exception.BizException;
import com.bflow.commons.service.BaseService;
import com.bflow.commons.util.StrUtil;
import com.bflow.dao.BflowRunRecordDao;
import com.bflow.dao.po.BflowRunRecordPo;
import com.bflow.dao.po.BflowRunTaskPo;
import com.bflow.util.AssertUtil;
import com.bflow.util.BeanMapper;
import com.bflow.util.SysSeqUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 功能：BflowRunRecord 流程记录-实现业务接口
 * 作者：haowen
 * 日期：2018-12-13
 */
@Service("bflowRunRecordService")
public class BflowRunRecordServiceImpl extends BaseService<BflowRunRecordPo, BflowRunRecordBo> implements IBflowRunRecordService<BflowRunRecordPo, BflowRunRecordBo> {


	@Autowired
	private IBflowRunInstanceService<?, BflowRunInstanceBo> bflowRunInstanceService;
	@Autowired
	private IBflowRunTaskService<?, BflowRunTaskBo> bflowRunTaskService;
	@Autowired
	private IBflowDefineActService<?, BflowDefineActBo> bflowDefineActService;
	@Autowired
	private IBflowExtResService bflowExtResService;

	@Autowired
	private BflowRunRecordDao dao;

	@Override
	protected BflowRunRecordDao getDao() {
		return dao;
	}

	@Override
	public void add(BflowRunRecordBo bo) {
		bo.setId(SysSeqUtil.genId());
		bo.setCreateTime(new Date());
		bo.setDelFlag(CommStatus.Y.getCode());
		BflowRunRecordPo po = BeanMapper.map(bo, BflowRunRecordPo.class);
		if (dao.insert(po) <= 0) {
			throw new BizException("新增失败");
		}
	}

	@Override
	public List<BflowRunRecordBo> findListByInstanceId(String instanceId) {
		AssertUtil.isNotEmpty(instanceId,"instanceId must be not null");
        BflowRunRecordQueryParam queryParam = new BflowRunRecordQueryParam();
        queryParam.addExtendParam("instanceId",instanceId);
        queryParam.addExtendParam("delFlag",CommConst.STATUS_Y);
        queryParam.setOrderDefParam("CREATE_TIME","DESC");
        List<BflowRunRecordBo> recordList = this.dao.getListByInstanceId(queryParam);
		return recordList;
	}

	@Override
	public List<BflowRunRecordBo> findListByBsId(String busiKey, String busiId, String busiSubId) {
		if(StringUtils.isBlank(busiKey) && StringUtils.isBlank(busiId) && StringUtils.isBlank(busiSubId)){
			return new ArrayList<>();
		}
		BflowRunInstanceBo instanceInfo = bflowRunInstanceService.findByBsId(busiKey, busiId, busiSubId);
		AssertUtil.isNotNull(instanceInfo,"流程实例不存在");
        List<BflowRunRecordBo> runRecordBos = this.findListByInstanceId(instanceInfo.getProcKey());
        return runRecordBos;
	}

	@Override
	public BflowRunRecordBo getLastRecordByInstanceId(String instanceId) {
        List<BflowRunRecordBo> recordBoList = this.findListByInstanceId(instanceId);
        if(CollectionUtils.isNotEmpty(recordBoList)){
            return recordBoList.get(0);
        }
        return null;
	}

	@Override
	public List<BflowRunRecordBo> getFullList(BflowRunInstanceBo instanceBo, String[] allActArray, String[] allProcessUserIds, String currUserId) {
		Map<String, BflowRunRecordBo> runRecordBoMap = new HashMap<>();
		List<BflowRunRecordBo> result = new ArrayList<>();
		String instanceId = instanceBo.getId();
		BflowRunRecordBo queryRecordBo = new BflowRunRecordBo();
		queryRecordBo.setDelFlag(CommConst.STATUS_Y);
		queryRecordBo.setInstanceId(instanceId);
		List<BflowRunRecordBo> recordBos = getListBy(queryRecordBo);
		if (CollectionUtils.isNotEmpty(recordBos)) {
			for (BflowRunRecordBo recordBo : recordBos) {
				if (recordBo != null && StringUtils.isNotBlank(recordBo.getCurActId()))
					runRecordBoMap.put(recordBo.getCurActId(), recordBo);
			}
		}

		//设置发起申请记录
		BflowRunRecordBo startRecord = new BflowRunRecordBo();
		startRecord.setCreateUname(instanceBo.getStartUid().equals(currUserId) ? "我" : instanceBo.getStartUname());
		startRecord.setFlag("发起申请");
		startRecord.setCreateTime(instanceBo.getCreateTime());
		result.add(startRecord);

		//渲染 所有活动
		if (ArrayUtils.isNotEmpty(allActArray)) {
			String auditUserId = null;
			int recordDepth = 0;
			for (int i = 0; i < allActArray.length; i++) {
				String actId = allActArray[i];
				//设置审批记录
				BflowRunRecordBo recordBo = runRecordBoMap.get(actId);
				if(recordBo == null)
					recordBo = runRecordBoMap.get(actId+"_"+i); //兼容 请假

				if (recordBo != null) {   //当前审批人有处理记录
					recordBo.setCurActName(bflowDefineActService.getCacheActName(actId));
					recordDepth++;
				} else {     //当前审批人无处理记录
					auditUserId = allProcessUserIds[i];
					recordBo = new BflowRunRecordBo();
					recordBo.setCurActName(bflowDefineActService.getCacheActName(actId));
					recordBo.setCreateUname(auditUserId.equals(currUserId) ? "我" : bflowExtResService.getUserNameOrRoleName(auditUserId));
					if (i == 0 || i == recordDepth) {  //第一个审批人而且无处理记录
						recordBo.setFlag("待审批");
						//处理分派类型的 用户
						if(StrUtil.containsChinese(auditUserId)){
							String name = auditUserId.equals(currUserId) ? "我" : getTaskUserName(instanceId, actId);
							if(name != null)
								recordBo.setCreateUname(name);
						}
					}
					if (FlowRunInstanceStatus.FINISH.eq(instanceBo.getStatus())) {    //设置流程结束时未处理人的记录
						recordBo.setFlag("已结束,无需审批");
					}
				}
				result.add(recordBo);
			}
		}
		//设置流程结束记录
//		if (FlowRunInstanceStatus.FINISH.eq(instanceBo.getStatus())) {
//			BflowRunRecordBo endRecord = new BflowRunRecordBo();
//			endRecord.setFlag("结束");
//			endRecord.setCreateTime(instanceBo.getEndTime());
//			result.add(endRecord);
//		}
		return result;
	}

	private String getTaskUserName(String instanceId, String actId){
		List<BflowRunTaskBo> taskBos = bflowRunTaskService.findWaitTaskList(instanceId);
		if(CollectionUtils.isNotEmpty(taskBos)){
			for (BflowRunTaskBo taskBo : taskBos) {
				if(taskBo.getActId().equals(actId)){
					return bflowExtResService.getUserNameOrRoleName(taskBo.getUserKey());
				}
			}
		}
		return null;
	}

}
